package com.tianji.aigc.memory;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.tianji.aigc.config.ToolResultHolder;
import lombok.Data;
import org.checkerframework.framework.qual.RequiresQualifier;
import org.springframework.ai.chat.messages.*;
import org.springframework.ai.model.Media;

import java.util.List;
import java.util.Map;

import static com.tianji.aigc.constants.Constants.ID;
import static com.tianji.aigc.constants.Constants.REQUEST_ID;

@Data
public class ChatMessage {
    private MessageType messageType;
    private Map<String, Object> metadata = Map.of();
    private List<Media> media = List.of();
    private List<AssistantMessage.ToolCall> toolCalls = List.of();
    private String textContent;
    private List<ToolResponseMessage.ToolResponse> toolResponses = List.of();
    private Map<String, Object> params = Map.of();

    /**
     * 1、将Message对象转换为Redis存储格式的JSON字符串
     *
     * @param message 需要转换的原始消息对象
     * @return 符合Redis存储规范的JSON字符串
     */
    public static String toJson(Message message) {
        // 1、拷贝Message属性至 ChatMessage对象
        ChatMessage chatMessage = BeanUtil.toBean(message, ChatMessage.class);
        // 2、单独设置消息内容
        chatMessage.setTextContent(message.getText());
        // 3、单独设置工具调用信息
        if (message instanceof AssistantMessage assistantMessage) {
            chatMessage.setToolCalls(assistantMessage.getToolCalls());

            // 解决会话记忆 丢失课程卡片参数Bug
            String messageId = Convert.toStr(message.getMetadata().get(ID));
            String requestId =  Convert.toStr(ToolResultHolder.get(messageId, REQUEST_ID));
            Map<String, Object> params = ToolResultHolder.get(requestId);
            if(ObjectUtil.isNotEmpty(params)){
                chatMessage.setParams(params);
            }
            ToolResultHolder.remove(messageId);  // 删除 messageId 与 requestId 的临时关联关系
        }
        if (message instanceof ToolResponseMessage toolResponseMessage) {
            chatMessage.setToolResponses(toolResponseMessage.getResponses());
        }

        // 4、将 ChatMessage 转为 JSON返回
        return JSONUtil.toJsonStr(chatMessage);
    }

    /**
     * 2、将Redis存储的JSON字符串反序列化为对应的Message对象
     *
     * @param json Redis存储的JSON格式消息数据
     * @return 对应类型的Message对象
     * @throws RuntimeException 当无法识别的消息类型时抛出异常
     */
    public static Message toMessage(String json) {
        ChatMessage chatMessage = JSONUtil.toBean(json, ChatMessage.class);
        switch (chatMessage.getMessageType()) {
            case SYSTEM -> {
                return new SystemMessage(chatMessage.getTextContent());
            }
            case USER -> {
                return new UserMessage(chatMessage.getTextContent(), chatMessage.getMedia(), chatMessage.getMetadata());
            }
            case ASSISTANT -> {
                // 解决根据会话ID查询历史会话记录，课程卡片json反显问题
                return new MyAssistantMessage(chatMessage.getTextContent(), chatMessage.getMetadata(), chatMessage.getToolCalls(),chatMessage.getParams());
            }
            case TOOL -> {
                return new ToolResponseMessage(chatMessage.getToolResponses(), chatMessage.getMetadata());
            }
        }
        throw new RuntimeException("Message data conversion failed.");
    }
}